﻿using WRJClient.UI.Map;
using WRJClient.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Threading;
using WRJClient.Common;
using WRJClient.Utils;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Symbology;
using Esri.ArcGISRuntime.UI;

namespace WRJClient.ViewModel
{

    public class UAVViewModel : BaseViewModel<UAVModel>, IMapObject
    {
        private BaseGraphic _gBody = new BaseGraphic();
        private BaseGraphic _gTrack = new BaseGraphic();
        private BaseGraphic _gLabel = new BaseGraphic();

        public bool Visable
        {
            get { return _gBody.IsVisible || _gTrack.IsVisible || _gLabel.IsVisible; }
            set
            {
                _gBody.IsVisible = value;
                _gTrack.IsVisible = value;
                _gLabel.IsVisible = value;
            }
        }

        private bool _isOnline = false;
        private TelemetryModel _telemetry = new TelemetryModel();
        

        public bool IsOnline
        {
            get
            {
                return _isOnline;
            }
            set
            {
                if (_isOnline != value)
                {
                    _isOnline = value;
                    if (_isOnline)
                    {
                        _onlineTimer.Start();
                    }
                    else
                    {
                        _onlineTimer.Stop();
                    }
                    OnPropertyChanged();
                    InitGraphics();
                }
            }
        }

        public string ImageUrl
        {
            get
            {
                string url = "";
                if (!string.IsNullOrEmpty(StaticData.Image))
                {
                    url = string.Format("http://{0}:{1}/{2}", Properties.Settings.Default.ServerIp, Properties.Settings.Default.ServerPort, StaticData.Image);
                }
                return url;
            }
        }

        public TelemetryModel Telemetry
        {
            get { return _telemetry; }
            set
            {
                if (_telemetry != value)
                {
                    _telemetry = value;
                    OnPropertyChanged();
                    addFlightPoint(_telemetry.Longitude, _telemetry.Latitude);
                    InitGraphics();
                }
            }
        }

        public bool IsVisable
        {
            get { return _gBody.IsVisible; }
            set { if (_gBody.IsVisible != value) { _gBody.IsVisible = value; OnPropertyChanged(); }; }
        }
        public bool IsTrackVisable
        {
            get { return _gTrack.IsVisible; }
            set
            {
                if (_gTrack.IsVisible != value)
                {
                    _gTrack.IsVisible = value;

                    OnPropertyChanged();
                };
            }
        }
        public bool IsAirLineVisable
        {
            get
            {
                MissionViewModel missionViewModel = MissionManager.Instance.GetCurrentByUavId(StaticData.UavId);
                if (missionViewModel != null)
                {
                    AirlineViewModel airlineViewModel = AirlineManager.Instance.Get(missionViewModel.StaticData.AirlineId);
                    if (airlineViewModel != null)
                    {
                        return airlineViewModel.IsVisable;
                    }
                }
                return false;
            }
            set
            {
                MissionViewModel missionViewModel = MissionManager.Instance.GetCurrentByUavId(StaticData.UavId);
                if (missionViewModel != null)
                {
                    AirlineViewModel airlineViewModel = AirlineManager.Instance.Get(missionViewModel.StaticData.AirlineId);
                    if (airlineViewModel != null)
                    {
                        if (airlineViewModel.IsVisable != value)
                        {
                            airlineViewModel.IsVisable = value;
                            OnPropertyChanged();
                        }
                    }
                }
            }
        }
        public bool IsLabelVisable
        {
            get { return _gLabel.IsVisible; }
            set { if (_gLabel.IsVisible != value) { _gLabel.IsVisible = value; OnPropertyChanged(); }; }
        }
        public bool IsEnabled { get { return ArcgisUtils.IsExtentValid(_gBody.Geometry.Extent); } }

        private PointCollection _flightPoints = new PointCollection(SpatialReferences.Wgs84);
        private readonly int FLIGHTPOINTSMAX = 5000;

        private TimeOut _onlineTimeout = null;
        private DispatcherTimer _onlineTimer = null;

        public UAVViewModel(UAVModel model = null) : base(model)
        {
            InitGraphics();
            _onlineTimeout = new TimeOut(5 * 1000);
            _onlineTimer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) };
            _onlineTimer.Tick += _onlineTimer_Tick;
            _gTrack.IsVisible = false;
        }

        private void _onlineTimer_Tick(object sender, EventArgs e)
        {
            if (_onlineTimeout.IsTimeout())
            {
                IsOnline = false;
            }
        }

        public void ClearFlightPoint()
        {
            _clearFlightPoint();
            InitGraphics();
        }

        private void _clearFlightPoint()
        {
            lock (this)
            {
                _flightPoints.Clear();
            }
        }

        private void addFlightPoint(double x, double y)
        {
            lock (this)
            {
                if (_flightPoints.Count > 0)
                {
                    MapPoint last = _flightPoints.ElementAt(_flightPoints.Count - 1);
                    if (last.X == x && last.Y == y)
                    {
                        return;
                    }
                }
                _flightPoints.Add(new MapPoint(x, y, SpatialReferences.Wgs84));
                while (_flightPoints.Count > FLIGHTPOINTSMAX)
                {
                    _flightPoints.RemoveAt(0);
                }
            }
        }

        public void HeartBeat()
        {
            IsOnline = true;
            _onlineTimeout.Restart();
        }

        public void InitGraphics()
        {
            string status = "online";
            if (IsOnline)
            {
                status = "online";
            }
            else
            {
                status = "offline";
            }
            string type = "固定翼";
            switch (StaticData.Type)
            {
                case "YATP01":
                    type = "YATP01";
                    break;
                case "ax5j":
                    type = "ax5j";
                    break;
                case "ax40":
                    type = "ax40";
                    break;
                case "v330":
                    type = "v330";
                    break;
                default:
                    break;
            }

            GraphicFactory.CreateImageGraphic(_gBody, StaticData.DbId, GraphicPart.Base, SymbolHelper.Instance.GetPictureMarkerSymbolInfo(GetType(), type, status), Telemetry.Longitude, Telemetry.Latitude, Telemetry.Yaw);
            GraphicFactory.CreateLineGraphic(_gTrack, StaticData.DbId, GraphicPart.UavFlightPath, SymbolHelper.Instance.GetLineSymbolInfo(GetType(), "航迹"), _flightPoints);
            string label = StaticData.UavId;
            if (StaticData.UavId.Length > 3)
            {
                label = StaticData.UavId.Substring(StaticData.UavId.Length - 3);
            }
            GraphicFactory.CreateTextGraphic(_gLabel, StaticData.DbId, GraphicPart.Label, SymbolHelper.Instance.GetTextSymbolInfo(GetType()), label, Telemetry.Longitude, Telemetry.Latitude);

            OnPropertyChanged("IsEnabled");
        }

        public void AddGraphics()
        {
            MapManager.Instance.AddGraphic("Layer3", _gBody);
            MapManager.Instance.AddGraphic("Layer2", _gTrack);
            MapManager.Instance.AddGraphic("Layer4", _gLabel);
        }

        public void RemoveGraphics()
        {
            MapManager.Instance.RemoveGraphic("Layer3", _gBody);
            MapManager.Instance.RemoveGraphic("Layer2", _gTrack);
            MapManager.Instance.RemoveGraphic("Layer4", _gLabel);
        }
    }
}
